/*
 * CCVisu is a tool for visual graph clustering
 * and general force-directed graph layout.
 * This file is part of CCVisu.
 *
 * Copyright (C) 2005-2012  Dirk Beyer
 *
 * CCVisu is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * CCVisu is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with CCVisu; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Please find the GNU Lesser General Public License in file
 * license_lgpl.txt or http://www.gnu.org/licenses/lgpl.txt
 *
 * Dirk Beyer    (firstname.lastname@uni-passau.de)
 * University of Passau, Bavaria, Germany
 */
package org.sosy_lab.ccvisu.ui;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;

import org.sosy_lab.ccvisu.graph.GraphData;
import org.sosy_lab.ccvisu.graph.GraphVertex;
import org.sosy_lab.ccvisu.graph.Group;
import org.sosy_lab.ccvisu.graph.PatternMode;

@SuppressWarnings("serial")
public class DialogEditGroup extends JDialog {
  private JDialog                             patternDialog = null;

  private final JButton                       addNode       = new JButton("Add");
  private final JButton                       addPattern    = new JButton("Add (pattern)");
  private final JButton                       filter        = new JButton("filter (pattern)");
  private final JButton                       remove        = new JButton("Remove");

  private DefaultListModel<GraphVertex> groupNodesModel;
  private DefaultListModel<GraphVertex> graphNodesModel;
  private JList<GraphVertex>            graphNodesList;
  private JList<GraphVertex>            groupNodesList;

  private JTextField                          textField;
  private JComboBox<PatternMode>              mode;                                           // equals,contains,...
  private JComboBox<String>                   mode2;                                          // keep, remove

  private final Group                         dialogGroup;
  private final GraphData                     dialogGraph;


  /**
   *
   */
  public DialogEditGroup(GraphData pGraph, Group pGroup) {
    this.dialogGroup = pGroup;
    this.dialogGraph = pGraph;

    initializeComponents();
    refreshGroupNodes();
    registerActionListeners();
  }

  private void initializeComponents() {
    //construct the choices for a later usage
    //it always use the same object => it "remembers" last choice
    mode = new JComboBox<PatternMode>(PatternMode.values());

    mode2 = new JComboBox<>();
    mode2.addItem("Keep");
    mode2.addItem("Remove");

    groupNodesModel = new DefaultListModel<>();
    groupNodesList = new JList<>(groupNodesModel);
    groupNodesList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);

    graphNodesModel = new DefaultListModel<>();
    graphNodesList = new JList<>(graphNodesModel);
    graphNodesList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    for (GraphVertex lCurrVertex : dialogGraph.getVertices()) {
      graphNodesModel.addElement(lCurrVertex);
    }

    JPanel up = new JPanel(new GridLayout(1, 2, 20, 10));
    up.add(new JLabel("Vertices of " + dialogGroup.getName()));
    up.add(new JLabel("List of all vertices"));
    this.add(up, BorderLayout.NORTH);

    JPanel center = new JPanel(new GridLayout(1, 2, 20, 10));
    center.add(new JScrollPane(groupNodesList));
    center.add(new JScrollPane(graphNodesList));
    this.add(center, BorderLayout.CENTER);

    JPanel buttons = new JPanel();
    buttons.add(addNode);
    buttons.add(addPattern);
    buttons.add(filter);
    buttons.add(remove);
    this.add(buttons, BorderLayout.SOUTH);

    this.setTitle(dialogGroup.getName());
    this.setSize(500, 400);
    this.setLocationRelativeTo(this);// center of screen
  }

  /**
   * refresh the list that contains the nodes of the current group
   */
  private void refreshGroupNodes() {
    groupNodesModel.removeAllElements();
    for (GraphVertex lCurrVertex : dialogGroup.getNodes()) {
      groupNodesModel.addElement(lCurrVertex);
    }

    dialogGraph.notifyAboutGroupsChange(null);
  }

  private void registerActionListeners() {
    this.addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosing(WindowEvent evt) {
        DialogEditGroup.this.setVisible(false);
        DialogEditGroup.this.dispose(); // Close.
      }
    });

    addNode.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        for (GraphVertex vertex: graphNodesList.getSelectedValuesList()) {
          dialogGroup.addNode(vertex);
        }
        refreshGroupNodes();
        signalChangedGroup();
      }
    });

    remove.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        // affect selected node to the default group
        for (GraphVertex vertex: groupNodesList.getSelectedValuesList()) {
          dialogGroup.removeNode(vertex, true);
        }
        refreshGroupNodes();
        signalChangedGroup();
      }
    });

    addPattern.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        patternDialog = new JDialog(DialogEditGroup.this, "Enter a pattern", true);

        textField = new JTextField(30);
        JPanel center = new JPanel(new GridLayout(2, 1));
        center.add(textField);
        center.add(mode);
        patternDialog.add(center, BorderLayout.CENTER);

        JButton ok = new JButton("Ok");
        JButton cancel = new JButton("Cancel");
        JPanel btt = new JPanel();
        btt.add(ok);
        btt.add(cancel);
        patternDialog.add(btt, BorderLayout.SOUTH);

        AddPatternOk listener = new AddPatternOk();

        textField.addKeyListener(listener);
        ok.addActionListener(listener);

        cancel.addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent arg0) {
            patternDialog.setVisible(false);
            patternDialog.dispose();
          }
        });

        patternDialog.pack();
        patternDialog.setLocationRelativeTo(null);// center of screen
        patternDialog.setVisible(true);
      }
    });

    filter.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        patternDialog = new JDialog(DialogEditGroup.this, "Enter a pattern", true);

        textField = new JTextField(30);
        JPanel center = new JPanel(new GridLayout(3, 1));
        center.add(textField);
        center.add(mode);
        center.add(mode2);
        patternDialog.add(center, BorderLayout.CENTER);

        JButton ok = new JButton("Ok");
        JButton cancel = new JButton("Cancel");
        JPanel btt = new JPanel();
        btt.add(ok);
        btt.add(cancel);
        patternDialog.add(btt, BorderLayout.SOUTH);

        FilterPatternOk listener = new FilterPatternOk();
        textField.addKeyListener(listener);
        ok.addActionListener(listener);

        cancel.addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent arg0) {
            patternDialog.setVisible(false);
            patternDialog.dispose();
          }
        });
        patternDialog.pack();
        patternDialog.setLocationRelativeTo(null);// center of screen
        patternDialog.setVisible(true);
      }
    });
  }

  private class AddPatternOk extends KeyAdapter implements ActionListener {

    //ok button event
    //same effect as Enter key
    @Override
    public void actionPerformed(ActionEvent arg0) {
      process();
    }

    //Enter key
    //same effect as ok button
    @Override
    public void keyPressed(KeyEvent e) {
      if (e.getKeyCode() == KeyEvent.VK_ENTER) {
        process();
      }
    }

    private void process() {
      String pattern = textField.getText();
      if (pattern != null) {
        dialogGroup.addViaPattern(pattern, (PatternMode) mode.getSelectedItem());
        refreshGroupNodes();
        signalChangedGroup();
      }
      textField = null;
      patternDialog.setVisible(false);
      patternDialog.dispose();
    }
  }

  private class FilterPatternOk extends KeyAdapter implements ActionListener {

    //ok button event
    //same effect as Enter key
    @Override
    public void actionPerformed(ActionEvent arg0) {
      process();
    }

    //Enter key
    //same effect as ok button
    @Override
    public void keyPressed(KeyEvent e) {
      if (e.getKeyCode() == KeyEvent.VK_ENTER) {
        process();
      }
    }

    private void process() {
      String pattern = textField.getText();
      if (pattern != null) {
        boolean keep = true;
        if (mode2.getSelectedIndex() == 1) {
          keep = false;
        }
        dialogGroup.filter(pattern, (PatternMode) mode.getSelectedItem(), keep);
        refreshGroupNodes();
        signalChangedGroup();
      }
      textField = null;
      patternDialog.setVisible(false);
      patternDialog.dispose();
    }
  }

  private void signalChangedGroup() {
    // TODO
  }
}
